using BootstrapBlazorApp.Server.LLMs.function;
using BootstrapBlazorApp.Server.LLMs.messages;
using Newtonsoft.Json;
using System.Reflection;

namespace BootstrapBlazorApp.Server.LLMs.utils;

public class FunctionParserUtil
{
    public static List<FunctionInput> ParseFunction(Type type)
    {
        List<FunctionInput> inputs = [];
        
        
        MethodInfo[] methodInfos = type.GetMethods();
        foreach (MethodInfo methodInfo in methodInfos)
        {
            var attribute = methodInfo.GetCustomAttribute<FunctionDescription>();
            if (attribute == null)
            {
                continue;
            }

            Function function = new Function { Name = methodInfo.Name, Description = attribute.Description };
            var dic = new Dictionary<string, ArgDescription>();
            List<string> required = [];
            foreach (var parameterInfo in methodInfo.GetParameters())
            {
                var customAttribute = parameterInfo.GetCustomAttribute<FunctionArg>();
                
               
                if (customAttribute == null||parameterInfo.Name==null)
                {
                    continue;
                }

                ArgDescription argDescription = new ArgDescription { Description = customAttribute.Description, Type = parameterInfo.ParameterType.Name };
                dic.Add(parameterInfo.Name, argDescription);
                required.Add(parameterInfo.Name);
                if (dic.Count <= 0)
                {
                    continue;
                }

                function.Parameters = new Parameters { Properties = dic };
                function.Required = required.ToArray();

            }
            inputs.Add(new FunctionInput { Function = function });
        }
        return inputs;
    }

    public static dynamic? ExecuteTongYiFunction(Type type, ReturnMessage returnMessage)
    {
        if (returnMessage.ToolCalls == null)
        {
            return null;
        }
        string? functionName = returnMessage.ToolCalls.FirstOrDefault()?.Function.Name;
        string str = returnMessage.ToolCalls.FirstOrDefault()?.Function.Arguments??"";
        if (functionName == null)
        {
            return null;
        }

        MethodInfo? methodInfo = type.GetMethod(functionName);
        if (methodInfo==null)
        {
            return null;
        }
        var instance = Activator.CreateInstance(type);
        ParameterInfo[] parameterInfos = methodInfo.GetParameters();
        List<object> param = [];
        Dictionary<string, string>? functionArguments = JsonConvert.DeserializeObject<Dictionary<string, string>>(str);
        foreach (var parameterInfo in parameterInfos)
        {
            if (parameterInfo.Name!=null&&functionArguments?[parameterInfo.Name] != null)
            {
                param.Add(functionArguments[parameterInfo.Name]);
            }
        }
        return methodInfo.Invoke(instance, param.ToArray());

    }

}
